package com.li.onjava8.concurrent.under.sync;

import com.li.onjava8.concurrent.utils.Nap;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 使用 synchronized 关键字，你不能尝试获得锁并让其失败，
 * 或者你在一段时间内尝试获得锁，然后放弃——为此，你必须使用这个并发库。
 *
 * ReentrantLock 可以尝试或者放弃获取锁，因此如果某些任务已经拥有锁，你可以决定放弃并执行其他
 * 操作，而不是一直等到锁释放，就像 untimed() 方法那样。而在 timed() 方法中，则尝试获取可能
 * 在 2 秒后没成功而放弃的锁。
 */
public class AttemptLocking {
    private ReentrantLock lock = new ReentrantLock();

    public void untimed() {
        boolean captured = lock.tryLock();
        try {
            System.out.println("tryLock()" + captured);
        } finally {
            if (captured)
                lock.unlock();
        }
    }

    public void timed() {
        boolean captured = false;
        try {
            captured = lock.tryLock(2, TimeUnit.SECONDS);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        try {
            System.out.println("tryLock(2, TimeUnit.SECONDS): " + captured);
        } finally {
            if (captured)
                lock.unlock();
        }
    }

    public static void main(String[] args) {
        AttemptLocking al = new AttemptLocking();
        al.untimed();
        al.timed();
        CompletableFuture.runAsync(() -> {
            al.lock.lock();
            System.out.println("acquired");
        });
        new Nap(0.1);
        al.untimed();
        al.timed();
    }
    /**
     * 显式锁比起内置同步锁提供更细粒度的加锁和解锁控制。这对于实现专门的同步并发结构，比如用于遍
     * 历链表节点的 交替锁 ( hand-over-hand locking ) ，也称为 锁耦合 （ lock coupling ）- 该遍历代码要求
     * 必须在当前节点的解锁之前捕获下一个节点的锁。
     */
}
